package cn.topcodes.tcsf.app.service;

import cn.topcodes.tcsf.admin.commons.domain.Page;
import cn.topcodes.tcsf.admin.commons.generic.IGenericService;
import cn.topcodes.tcsf.app.domain.form.AppClientInfo;
import cn.topcodes.tcsf.app.domain.entity.AppUser;
import cn.topcodes.tcsf.app.domain.report.RespAppUserInfo;
import cn.topcodes.tcsf.app.domain.report.UserRetentionVo;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * @author Unicorn
 */
public interface AppUserService extends IGenericService<AppUser> {

    /**
     * 用户参数取值允许重复
     */
    public static final String USER_PARAM_VALUE_REPEAT_ALLOW = "USER_PARAM_VALUE_REPEAT_ALLOW";

    /**
     * 用户参数取值重复则覆盖
     */
    public static final String USER_PARAM_VALUE_REPEAT_OVERRIDE = "USER_PARAM_VALUE_REPEAT_OVERRIDE";

    /**
     * 用户参数取值重复则忽略
     */
    public static final String USER_PARAM_VALUE_REPEAT_IGNORE = "USER_PARAM_VALUE_REPEAT_IGNORE";


    /**
     * 注册APP用户
     *
     * @param username 用户名
     * @param password 密码
     * @param realName 真实姓名
     * @return app用户对象
     */
    AppUser register(String username, String password, String realName);

    /**
     * 账号登录
     * 登录默认APP
     *
     * @param username 用户名
     * @param password 密码
     * @return 用户凭证
     */
    public String login(String username, String password);

    /**
     * 登录并提交客户端信息
     *
     * @param username      用户名
     * @param password      密码
     * @param appClientInfo 客户端信息
     * @return token
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    String login(String username, String password, AppClientInfo appClientInfo);

    /**
     * 验证用户名密码
     *
     * @param username 用户名
     * @param password 密码
     * @return 用户信息，用户名密码将抛出异常
     */
    AppUser validPassword(String username, String password);

    /**
     * 获取指定app，用户的语言
     *
     * @param app       app
     * @param appUserId app用户id
     * @return 语言
     */
    String getLanguage(String app, Long appUserId);

    /**
     * 获取默认app，用户的语言
     *
     * @param appUserId
     * @return
     */
    String getLanguage(Long appUserId);

    /**
     * 设置默认app，用户的语言
     *
     * @param appUserId app用户id
     * @param language  语言
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void setLanguage(Long appUserId, String language);

    /**
     * 设置指定app，用户的语言
     *
     * @param app       app
     * @param appUserId app用户ID
     * @param language  语言
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void setLanguage(String app, Long appUserId, String language);

    /**
     * 获取默认app，用户的APP版本信息
     *
     * @param appUserId app用户ID
     * @return app版本信息
     */
    String getAppVersion(Long appUserId);

    /**
     * 获取指定app，用户的app版本信息
     *
     * @param app       app
     * @param appUserId app用户ID
     * @return app版本信息
     */
    String getAppVersion(String app, Long appUserId);

    /**
     * 在默认app，设置用户的app版本信息
     *
     * @param appUserId  app用户ID
     * @param appVersion app版本信息
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void setAppVersion(Long appUserId, String appVersion);

    /**
     * 在指定app，设置用户的app版本信息
     *
     * @param app        app
     * @param appUserId  app用户ID
     * @param appVersion app版本信息
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void setAppVersion(String app, Long appUserId, String appVersion);

    /**
     * 获取默认app，用户的终端信息
     *
     * @param appUserId app用户ID
     * @return 终端信息
     */
    String getTerminal(Long appUserId);

    /**
     * 获取指定app，用户的终端信息
     *
     * @param app       app
     * @param appUserId app用户ID
     * @return 终端信息
     */
    String getTerminal(String app, Long appUserId);

    /**
     * 在默认app，设置用户的终端信息
     *
     * @param appUserId app用户ID
     * @param terminal  终端信息
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void setTerminal(Long appUserId, String terminal);

    /**
     * 在指定app，设置用户的终端信息
     *
     * @param app       app
     * @param appUserId app用户ID
     * @param terminal  终端信息
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void setTerminal(String app, Long appUserId, String terminal);

    /**
     * 获取默认app，用户的平台信息
     *
     * @param appUserId app用户ID
     * @return 平台信息
     */
    String getPlatform(Long appUserId);

    /**
     * 获取指定app，用户的平台信息
     *
     * @param app       app
     * @param appUserId app用户ID
     * @return 平台信息
     */
    String getPlatform(String app, Long appUserId);

    /**
     * 在默认app，设置用户的终端信息
     *
     * @param appUserId app用户ID
     * @param platform  平台信息
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void setPlatform(Long appUserId, String platform);

    /**
     * 在指定app，设置用户的终端信息
     *
     * @param app       app
     * @param appUserId app用户ID
     * @param platform  平台信息
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void setPlatform(String app, Long appUserId, String platform);

    /**
     * 更新默认app，用户活跃时间
     *
     * @param appUserId app用户ID
     */
    void active(Long appUserId);

    /**
     * 更新指定app，用户活跃时间
     *
     * @param app       app
     * @param appUserId app用户ID
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void active(String app, Long appUserId);

    /**
     * 账号退出
     * 退出默认APP
     *
     * @param token 用户凭证
     */
    public void logout(String token);

    /**
     * 退出指定app
     *
     * @param app   app
     * @param token 凭证
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void logout(String app, String token);

    /**
     * 修改密码
     *
     * @param id     用户ID
     * @param oldPwd 旧密码
     * @param newPwd 新密码
     */
    public void modifyPassword(Long id, String oldPwd, String newPwd);

    /**
     * 重置密码
     *
     * @param id       app用户ID
     * @param password 新密码
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void resetPassword(Long id, String password);

    /**
     * 通过token获取用户信息
     * 通过默认APP的token
     *
     * @param token 用户凭证
     * @return 用户信息
     */
    public AppUser findByToken(String token);

    /**
     * 通过token获取用户名
     * 通过默认APP的token
     *
     * @param token 用户凭证
     * @return 用户名
     */
    public String findUsernameByToken(String token);

    /**
     * 是否在线
     *
     * @param token 凭证
     * @return true：在线；false:离线
     */
    boolean isOnline(String token);

    /**
     * 通过用户名获取该用户所有token
     *
     * @param username 用户名
     * @return 凭证列表，在允许app用户在多设备登录时，一个app账号会存在多个凭证，目前仅支持一个凭证，即返回的列表最多只有一个元素
     */
    public List<String> findTokensByUsername(String username);

    /**
     * 根据用户名获取默认app的token
     *
     * @param username 用户名
     * @return 凭证
     */
    String findTokenByUsername(String username);

    /**
     * 获取用户在指定app上的token
     *
     * @param app       app
     * @param appUserId app用户ID
     * @return 凭证
     */
    String getAppToken(String app, Long appUserId);

    /**
     * 获取用户在指定app上的token列表
     *
     * @param app       app
     * @param appUserId app用户ID
     * @return 凭证列表
     */
    List<String> getAppTokens(String app, Long appUserId);

    /**
     * 通过用户名查找用户
     *
     * @param username 用户名
     * @return app用户信息对象
     */
    AppUser findByUsername(String username);

    /**
     * 更新app用户信息
     *
     * @param form 用户信息表单
     */
    void updateAppUser(AppUser form);

    /**
     * 删除用户参数
     * @param appUserId
     * @param name
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void deleteAppUserParam(Long appUserId, String name);

    /**
     * 设置用户参数
     *
     * @param appUserId app用户ID
     * @param name      参数名
     * @param value     参数值
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void setAppUserParam(Long appUserId, String name, Object value);

    /**
     * 设置用户参数
     *
     * @param appUserId        app用户ID
     * @param name             参数名
     * @param value            参数值
     * @param allowValueRepeat 是否允许取值重复，常量 USER_PARAM_VALUE_REPEAT_*
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    void setAppUserParam(Long appUserId, String name, Object value, String allowValueRepeat);

    /**
     * 获取用户参数
     *
     * @param appUserId    app用户ID
     * @param name         参数名
     * @param clazz        参数类型Class
     * @param defaultValue 默认值
     * @param <T>          参数类型，仅支持Integer、Long、Double、String、Boolean
     * @return 参数值
     */
    <T> T getAppUserParamValue(Long appUserId, String name, Class<T> clazz, T defaultValue);

    Page<AppUser> findPageAndSearchDate(Map<String, String[]> searchParams, int pageNumber, int pageSize);

    Page<AppUser> findPageAndSearchAccountOnline(Map<String, String[]> searchParams, int pageNumber, int pageSize);

    Page<AppUser> findPageAndSearchAccountActive(Map<String, String[]> searchParams, int pageNumber, int pageSize);

    Page<RespAppUserInfo> findPageAndSearchAccountByApp(Map<String, String[]> searchParams, int pageNumber, int pageSize);

    List<UserRetentionVo> getUserRetention(Map<String, String[]> searchParams);
}
